package com.周阳.代理模式.JDK动态代理;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

/**
 * JDK动态代理
 * ①：要求被代理对象必须有接口
 * ②：在获取代理类的时候必须使用抽象接口来接收返回值
 * ③：代理类和被代理类是不同类型的，代理类是JDK给我们创建的，并不是被代理的类型，所以在获取代理类的时候需要使用接口类型接收
 * ，因为代理类也是这个接口的实现类
 */
public class JDKProxy<T> implements InvocationHandler {

    /**
     * 被代理对象
     */
    private T target;

    public JDKProxy(T target) {
        this.target = target;
    }

    /**
     * getProxy()方法：获取代理对象
     * ----------------------
     * newProxyInstance（）方法的三个参数
     * ClassLoader loader：类加载器，用于加载代理类，可以通过目标对象来获取类加载器
     * Class<?>[] interfaces：代理类实现的接口-----一个类可以实现很多接口，所以是一个数组
     * InvocationHandler h ：代理对象的调用处理程序
     */
    public static<E> E getProxy(E t){
        Object o = Proxy.newProxyInstance(t.getClass().getClassLoader(),
                t.getClass().getInterfaces(),
                new JDKProxy(t));
        return (E)o;
    }

    /**
     * 目标方法在执行之前，会动态代理会先调用invoke()
     * 这时候我们就能实现前置增强
     */
    /**
     *
     * 参数1：proxy是代理对象
     * 参数2：method：被代理对象当前要调用的方法
     * 参数3：args：调用目标方法的实际参数
     * Object返回值：返回值就是目标方法的返回值
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //动态代理，执行目标对象的方法。result表示目标方法的返回值
        System.out.println("可以做前置增强");
        Object result = method.invoke(target, args);
        System.out.println("可以做后置增强");
        return result;
    }
}
